﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NFit.Core.Interfaces;
using System.IO;

namespace NFit.Core.Reports
{
    /// <summary>
    /// Report engine writing one file per specification
    /// </summary>
    public class FileSystemReport : IReportWriter
    {
        #region IReportWriter Members

        /// <summary>
        /// The root directory for the file source
        /// </summary>
        public string RootDirectory { get; set; }

        /// <summary>
        /// The extension of specification files
        /// </summary>
        public string SpecificationFileExtension { get; set; }

        /// <summary>
        /// The custom writer for the fixtures
        /// </summary>
        public ISpecificationWriter Writer { get; set; }

        /// <summary>
        /// Make the report for the associated summary
        /// </summary>
        /// <param name="summary"></param>
        public void Report(ExecutionSummary summary)
        {
            if (Writer == null)
                throw new ArgumentNullException("File system report expect a fixture writer");

            WriteSpecs(RootDirectory, summary.RunnedSpecs);
        }

        private void WriteSpecs(string basedir, IEnumerable<SpecificationDefinition> specs)
        {
            foreach (var spec in specs)
            {
                WriteSpec(basedir, spec);
            }
        }

        private string GetSpecFileName(string basedir, SpecificationDefinition spec)
        {
            string filename = spec.Name;
            if (string.IsNullOrEmpty(SpecificationFileExtension))
            {
                filename = filename + ".fit";
            }
            else
            {
                if (SpecificationFileExtension.StartsWith("."))
                {
                    filename = filename + SpecificationFileExtension;
                }
                else
                {
                    filename = filename + "." + SpecificationFileExtension;
                }
            }

            filename = Path.Combine(basedir, filename);

            return filename;
        }

        private void WriteSpec(string basedir, SpecificationDefinition spec)
        {
            if (!Directory.Exists(basedir))
            {
                Directory.CreateDirectory(basedir);
            }

            string filePath = GetSpecFileName(basedir, spec);
            
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            using (FileStream fs = File.OpenWrite(filePath))
            {
                Writer.Write(fs,spec,true,true);    
            }

            if (spec.ChildSpecs.Count > 0)
            {
                string childDir = Path.Combine(basedir, spec.Name);
                WriteSpecs(childDir, spec.ChildSpecs);
            }
        }

        #endregion
    }
}
